package com.xquant.pricing.calc.service.impl.otcOption.split;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.xquant.common.core.constant.DictConstant;
import com.xquant.pricing.calc.entity.CalcEngineParam4Simple;
import com.xquant.pricing.calc.entity.simple.*;
import com.xquant.pricing.calc.service.StockService;
import com.xquant.common.engine.xPP.request.CalcEngineParam;
import com.xquant.common.engine.xPP.request.CalcPricingParam;
import com.xquant.common.engine.xPP.request.Instrument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 功能说明：保本返息期权拆分
 * 编写作者：botao.yu
 * 开发日期：2021/11/17 18:47
 * 修改记录：修改日期   修改人    修改内容
 */
@Component
public class CalcCommonService4OtcOptionSplit4BasicSnow implements CalcCommonService4OtcOptionSplit {
    @Autowired
    private StockService stockService;

    @Override
    public CalcEngineParam split(CalcEngineParam4Simple sourceCalcEngineParam) {
        {
            CalcEngineParam engineParam = new CalcEngineParam();
            engineParam.setPriority("h");
            engineParam.setLocalLog("1");
            Instrument instrument = new Instrument();
            instrument.setProductType(DictConstant.OPTION_TYPE.ELN_ACB_BASICSNOWBALL.getCode());
            Record record = sourceCalcEngineParam.getRecord();
            BaseInfo baseInfo = record.getBaseInfo();
            OptionTrade OptionTrade = record.getOptionTrade();
            String productType = null;
            List<PremiumItem> premiumList = null;
            if (OptionTrade != null) {
                premiumList = OptionTrade.getPremium();
            }
            List<OptionLeg> legDataList = OptionTrade.getOptionLegs();
            LegData legData = null;
            if (legDataList.size() > 0) {
                productType = legDataList.get(0).getProductType();
                legData = legDataList.get(0).getLegData();
            }
            if (legData != null) {
                JSONObject termData = new JSONObject();
                //雪球结构拼装
                termData.put("productType", DictConstant.OPTION_TYPE.ELN_ACB_BASICSNOWBALL.getCode());
                termData.put("notional", legData.getNotional());
                termData.put("notionalCurrency", "CNY");
                termData.put("term", legData.getTerm());
//            termData.put("settlementType","C");
//            termData.put("settlementCurrency","CNY");
                termData.put("payDirection", DictConstant.IR_DIRECT.SELL.equals(legData.getTrdType()) ? DictConstant.DIRECT.BUY : DictConstant.DIRECT.SELL);
                termData.put("effectiveDate", legData.getEffectiveDate());
                termData.put("effectiveDateConv", "None");
                termData.put("effectiveDateCalendar", "CHINA_EX");
                termData.put("terminationDate", legData.getTerminationDate());
                termData.put("terminationDateConv", "FOLLOWING");
                termData.put("terminationDateCalendar", "CHINA_EX");
                JSONObject marginObj = new JSONObject();
                marginObj.put("marginAmount", "0");
                marginObj.put("overLoss", "0");
                termData.put("margin", marginObj);
                legData.setUnderlyerId(getInstructionId((String) legData.getUnderlyerId()));
                Map qryMap = new HashMap();
                qryMap.put("stockCode", legData.getUnderlyerId());
                qryMap.put("calDate", DateUtil.today());
                //去当前标的的最近收盘价
                Map priceMap = stockService.queryLastDateStockPrice(qryMap);
                termData.put("issuePrice", legData.getSpotPrice());
                if (StrUtil.isNotBlank(MapUtil.getStr(priceMap, "DP_CLOSE"))) {
                    termData.put("issuePrice", MapUtil.getStr(priceMap, "DP_CLOSE"));
                }
                String[] underLyerArray = {legData.getUnderlyerId()};
                termData.put("underlyerIds", underLyerArray);
                JSONObject knockOutObj = new JSONObject();
                knockOutObj.put("observeType", "Close");
                knockOutObj.put("observeRounding", "-1");
                knockOutObj.put("payDirection", DictConstant.IR_DIRECT.SELL.equals(legData.getTrdType()) ? DictConstant.DIRECT.SELL : DictConstant.DIRECT.BUY);
                //保底收益率
                JSONObject basicYieldObj = new JSONObject();
                JSONObject miniYieldObj = new JSONObject();
                MinimumYield[] miniYield = legData.getMinimumYields();
                if (miniYield.length > 0) {
                    basicYieldObj.put("paymentAmount", "");
                    basicYieldObj.put("daycounter", transferBasic(miniYield[0].getDayCounter(), miniYield[0].getIfAnnual()));
                    basicYieldObj.put("paymentAmountPecentage", miniYield[0].getYieldRate());
                    basicYieldObj.put("participationRate", "1");
                    miniYieldObj.put("paymentAmount", "");
                    miniYieldObj.put("daycounter", transferBasic(miniYield[0].getDayCounter(), miniYield[0].getIfAnnual()));
                    miniYieldObj.put("paymentAmountPecentage", miniYield[0].getYieldRate());
                    miniYieldObj.put("participationRate", "1");
                }
                JSONArray knoksArray = new JSONArray();
                JSONObject observeDate = new JSONObject();
                observeDate.put("endDate", legData.getEffectiveDate());
                observeDate.put("endDateConv", "FOLLOWING");
                observeDate.put("calendar", "CHINA_EX");
                JSONObject calclationPeriod = new JSONObject();
                calclationPeriod.put("startDate", legData.getEffectiveDate());
                calclationPeriod.put("startDateConv", "FOLLOWING");
                calclationPeriod.put("isIncludeStartDate", legData.getKnockOut().getCalclationPeriodInclude());
                calclationPeriod.put("endDate", legData.getEffectiveDate());
                calclationPeriod.put("endDateConv", "FOLLOWING");
                calclationPeriod.put("isIncludeEndDate", legData.getKnockOut().getCalclationPeriodInclude());
                calclationPeriod.put("calendar", "CHINA_EX");
                //得到敲出结构中的观察日期价格比例和票据数组
                String[] obsDateArray = StrUtil.isNotBlank(legData.getKnockOut().getObserveDates()) ? legData.getKnockOut().getObserveDates().split(";") : null;
                //敲出价格比例
                String[] triggerLevelRatesArray = StrUtil.isNotBlank(legData.getKnockOut().getTriggerLevelRates()) ? legData.getKnockOut().getTriggerLevelRates().split(";") : null;
                //票息
                String[] rebateRatesArray = StrUtil.isNotBlank(legData.getKnockOut().getRebateRates()) ? legData.getKnockOut().getRebateRates().split(";") : null;
                if (obsDateArray != null) {
                    for (int i = 0; i < obsDateArray.length; i++) {
                        JSONObject knocksObj = new JSONObject();
                        JSONObject triggerObj = new JSONObject();
                        triggerObj.put("type", "EqualOrGreater");
                        triggerObj.put("levelPercentage", "");//敲出比例 默认100
                        triggerObj.put("level", triggerLevelRatesArray[i]);
                        knocksObj.put("trigger", triggerObj);
                        observeDate.put("endDate", obsDateArray[i]);
                        knocksObj.put("observeDate", JSON.parseObject(JSON.toJSONString(observeDate)));
                        if (i == 0) {
                            calclationPeriod.put("startDate", legData.getEffectiveDate());
                        } else {
                            calclationPeriod.put("startDate", obsDateArray[i - 1]);
                        }
                        calclationPeriod.put("endDate", obsDateArray[i]);
                        knocksObj.put("calclationPeriod", JSON.parseObject(JSON.toJSONString(calclationPeriod)));
                        knocksObj.put("paymentDate", obsDateArray[i]);
                        knocksObj.put("paymentDateOffset", legData.getKnockOut().getPaymentDateOffset());
                        knocksObj.put("paymentDateConv", "FOLLOWING");
                        knocksObj.put("paymentDateCalendar", "CHINA_EX");
                        JSONObject yeildObj = new JSONObject();
                        yeildObj.put("daycounter", transferBasic(legData.getMinimumYields()[0].getDayCounter(), legData.getMinimumYields()[0].getIfAnnual()));
                        yeildObj.put("paymentAmountPecentage", rebateRatesArray[i]);
                        yeildObj.put("paymentAmount", "");
                        yeildObj.put("participationRate", "1");
                        knocksObj.put("basicYield", yeildObj);
                        knocksObj.put("calclationPeriod", JSON.parseObject(JSON.toJSONString(calclationPeriod)));
                        JSONArray miniYieldArray = new JSONArray();
                        miniYieldArray.add(JSON.parseObject(JSON.toJSONString(miniYieldObj)));
                        knocksObj.put("minimumYields", miniYieldArray);
                        knoksArray.add(knocksObj);
                    }
                }
                knockOutObj.put("knocks", knoksArray);
                termData.put("knockOut", knockOutObj);
                //拼装unTrigger
                JSONObject unTriggerObj = new JSONObject();
                unTriggerObj.put("payDirection", DictConstant.IR_DIRECT.SELL.equals(legData.getTrdType()) ? DictConstant.DIRECT.SELL : DictConstant.DIRECT.BUY);
                unTriggerObj.put("unTriggerType", "NoKnockOut");
                JSONObject calclationPeriodObj = new JSONObject();
                calclationPeriodObj.put("startDate", legData.getEffectiveDate());
                calclationPeriodObj.put("startDateConv", "Following");
                calclationPeriodObj.put("isIncludeStartDate", legData.getKnockOut().getCalclationPeriodInclude());
                calclationPeriodObj.put("isIncludeEndDate", legData.getKnockOut().getCalclationPeriodInclude());
                calclationPeriodObj.put("endDate", legData.getTerminationDate());
                calclationPeriodObj.put("endDateConv", "Following");
                calclationPeriodObj.put("calendar", "CHINA_EX");
                unTriggerObj.put("calclationPeriod", calclationPeriodObj);
                basicYieldObj.put("paymentAmountPecentage", legData.getUnTrigger().getRebateRate());
                unTriggerObj.put("basicYield", JSON.parseObject(JSON.toJSONString(basicYieldObj)));
                unTriggerObj.put("paymentDate", legData.getTerminationDate());
                unTriggerObj.put("paymentDateConv", "Following");
                unTriggerObj.put("paymentDateCalendar", "CHINA_EX");
                JSONArray miniYieldArray = new JSONArray();
                miniYieldArray.add(JSON.parseObject(JSON.toJSONString(miniYieldObj)));
                unTriggerObj.put("minimumYields", miniYieldArray);
                termData.put("unTrigger", unTriggerObj);
                instrument.setTermsheet(termData);
                instrument.setProductType(DictConstant.OPTION_TYPE.ELN_ACB_BASICSNOWBALL.getCode());
                engineParam.setInstrument(instrument);
                CalcPricingParam calPriceParamObj = new CalcPricingParam();
                calPriceParamObj.setValueDate(getCalcDate(sourceCalcEngineParam));
                engineParam.setCalcPricingParam(calPriceParamObj);
                return engineParam;
            }
            return null;
        }
    }

    @Override
    public CalcEngineParam split(CalcEngineParam sourceCalcEngineParam) {
        return null;
    }

    @Override
    public String getSplitCode() {
        return DictConstant.OPTION_TYPE.ELN_ACB_BASICSNOWBALL.getCode();
    }


}
